package com.scgri.main;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.scgri.config.Const;
import com.scgri.utils.ExcelUtil;
import com.scgri.utils.HttpUtil;
import com.scgri.utils.JDBCUtil;
import com.sun.org.apache.bcel.internal.generic.NEW;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.poi.util.StringUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

public class CheckData {

    public static void start() throws IOException {
        String json = IOUtils.toString(new FileInputStream(Const.FILE_INPUT_PATH),"UTF-8");
        List<Map> mapList = (List<Map>) JSON.parse(json);
        Map<String, List<Map>> sortMap = standardData();
        List<Map> level3 = sortMap.get("3");
        List<Map> level2 = sortMap.get("2");
        List<Map> level1 = sortMap.get("1");
        List<Map> level0 = sortMap.get("0");
        //存放成功数据
        List<Map> success = new ArrayList<>();
        //存放异常数据
        List<Map> fail = new ArrayList<>();
        for (int i = 0; i < mapList.size(); i++) {
            Map map = mapList.get(i);
            map.put("x","");
            map.put("y","");
            map.put("area_id","");
            map.put("area_code","");
            String s = new String("cause".getBytes(),"UTF-8");
            if("".equals(map.get("address"))){
                map.put(s, new String("address is null".getBytes(),"UTF-8"));
                fail.add(map);
                continue;
            }
            if (!level3.isEmpty() && check(level3, success, map)) {
                continue;
            }

            if (!level2.isEmpty() && check(level2, success, map)) {
                continue;
            }

            if (!level1.isEmpty() && check(level1, success, map)) {
                continue;
            }

            if (!level0.isEmpty() && check(level0, success, map)) {
                continue;
            }
            if(!map.containsKey("cause")){
                map.put(s, new String("this poi is repeat data or level mismatching".getBytes(),"UTF-8"));
            }
            fail.add(map);
        }

        serchPOIFromBaidu(sort(sortMap), success, fail);
        fileOutput(Const.FILE_OUTPUT_PATH, new String(Const.BAIDU_DEPARTMENT_NAME.getBytes(),"UTF-8") + new String("success".getBytes(),"UTF-8")+".xls", success);
        fileOutput(Const.FILE_OUTPUT_PATH, new String(Const.BAIDU_DEPARTMENT_NAME.getBytes(),"UTF-8") + new String("fail".getBytes(),"UTF-8")+".xls", fail);
    }

    /**
     * 检查数据方法
     *
     * @param maps    数据库查出的匹配数据
     * @param success 存放成功数据的集合
     * @param map     需要检测的POIMap
     * @return
     */
    public static Boolean check(List<Map> maps, List<Map> success, Map<String, String> map) throws UnsupportedEncodingException {
        String s = new String("cause".getBytes(),"UTF-8");
        for (int j = 0; j < maps.size(); j++) {

            String POIName = map.get(Const.POI_NAME);
            Map<String, String> map1 = maps.get(j);
            String shortName = map1.get("short_name");
            String name = map1.get("name");
            String mergerName = map1.get("merger_name");
            if (POIName.contains(name)) {
                map.remove(s);
                map.put("area_code", String.valueOf(map1.get("area_code")));
                success.add(map);
                maps.remove(j);
                return true;
            } else if (POIName.contains(shortName) && !Const.REPEAT_PLACE_NAME.contains(shortName) && !Const.SAME_PROVINCE_PLACE_NAME.contains(shortName)) {
                map.put("area_code", String.valueOf(map1.get("area_code")));
                map.remove(s);
                success.add(map);
                maps.remove(j);
                return true;
            } else if (POIName.contains(shortName) && Const.LEVEV1_CITY_NAME.contains(name)) {
                map.put("area_code", String.valueOf(map1.get("area_code")));
                map.remove(s);
                success.add(map);
                maps.remove(j);
                return true;
            } else if (POIName.contains(shortName)) {
                String address = map.get(Const.POI_ADDRESS);
                String[] split = mergerName.split(",");
                int index = split.length == 1 ? split.length : split.length-1 ;
                if (Const.REPEAT_PLACE_NAME.contains(shortName)) {
                    for (int i = 0; i < index; i++) {
                        if (address.contains(split[i])) {
                            map.remove(s);
                            map.put("area_code", String.valueOf(map1.get("area_code")));
                            success.add(map);
                            maps.remove(j);
                            return true;
                        }else if(i+1 == index){
                            map.put(s,new String("this poi is repeat place name,use address mismatching".getBytes(),"UTF-8"));
                        }
                    }
                } else if (Const.SAME_PROVINCE_PLACE_NAME.contains(shortName)) {
                    for (int i = 0; i < index; i++) {
                        if (address.contains(split[i]) && address.contains(name)) {
                            map.remove(s);
                            map.put("area_code", String.valueOf(map1.get("area_code")));
                            success.add(map);
                            maps.remove(j);
                            return true;
                        }else if(i+1 == index){
                            map.put(s,new String("this poi is same province place name".getBytes(),"UTF-8"));
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * 标准数据准备，按级别组合好
     *
     * @return
     */
    public static Map<String, List<Map>> standardData() {
        String sql = "";

        for (int i = 4 ; i > Const.LEVEL ; i--) {
            sql += " AND level != " + i;
        }

        System.out.println("SQL==" + Const.SQL + sql);
        List<Map> mapList = JDBCUtil.executeQuery(Const.SQL + sql);
        List<Map> level0 = new ArrayList<>();
        List<Map> level1 = new ArrayList<>();
        List<Map> level2 = new ArrayList<>();
        List<Map> level3 = new ArrayList<>();
        for (Map map : mapList) {
            String level = map.get("level").toString();
            if ("0".equals(level)) {
                level0.add(map);
            } else if ("1".equals(level)) {
                level1.add(map);
            } else if ("2".equals(level)) {
                level2.add(map);
            } else if ("3".equals(level)) {
                level3.add(map);
            }
        }
        Map<String, List<Map>> map = new HashMap<>();
        map.put("0", level0);
        map.put("1", level1);
        map.put("2", level2);
        map.put("3", level3);
        return map;
    }

    /**
     * 将未匹配到的数据格式化
     *
     * @param maps
     * @return
     */
    public static List<Map> sort(Map<String, List<Map>> maps) {
        List<Map> unmatchedMaps = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            List<Map> mapList = maps.get(String.valueOf(i));
            for (Map map : mapList) {
                unmatchedMaps.add(map);
            }
        }
        return unmatchedMaps;
    }

    /**
     * 文件输出方法
     *
     * @param path
     * @param list
     */
    public static void fileOutput(String path, String fileName, List<Map> list) {
        try {
            if ("".equals(path) && path.length() <= 0) {
                path = System.getProperty("user.dir") + "\\src\\main\\java\\com\\scgri\\result\\";
            }
            ExcelUtil.exportExcel(list, new File(path + fileName));
        } catch (Exception e) {
            System.out.println("文件输出异常");
            e.printStackTrace();
        }
    }

    /**
     * 从高德上面获取POI
     *
     * @param list
     * @param success
     */
    public static void serchPOIFromBaidu(List<Map> list, List<Map> success, List<Map> noSearchList) throws UnsupportedEncodingException {

        String baiduMapAPI = "https://api.map.baidu.com/";
        String gaodeMapAPI = "http://api.tianditu.gov.cn/search";
        for (Map<String, String> map : list) {
            HashMap<String, String> hashMap = new HashMap<>();
            hashMap.put("url", "https://api.map.baidu.com/");
            String area_code = String.valueOf(map.get("area_code"));
            String merger_name = map.get("merger_name");
            String cityName = merger_name.indexOf(",") == -1 ? map.get("name") : merger_name.substring(0, merger_name.lastIndexOf(",")).replace(",", "") + map.get("name");
            try {
                System.out.println(cityName + Const.BAIDU_DEPARTMENT_NAME);
                String baiduParam = "qt=s&c=1&wd="+URLEncoder.encode(cityName + Const.BAIDU_DEPARTMENT_NAME, "UTF-8")+"&rn=10&ie=utf-8&oue=1&fromproduct=jsapi&res=api&ak=E4805d16520de693a3fe707cdc962045";
                String baiduRes = HttpUtil.sendGet(baiduMapAPI, baiduParam);
                Map resMap = JSON.parseObject(new String(baiduRes.getBytes(),"UTF-8"), HashMap.class);
                List<Map> content = (List<Map>) resMap.get("content");
                Map<String,Object> poi = null;
                String name = "";
                if(CollectionUtils.isEmpty(content)){
                    String gaodeRes = HttpUtil.sendGet(gaodeMapAPI, "postStr={%22keyWord%22:%22"+URLEncoder.encode(cityName + Const.GAODE_DEPARTMENT_NAME, "UTF-8")+"%22,%22level%22:%2220%22,%22mapBound%22:%2288.24219,23.0393,117.55371,46.58907%22,%22queryType%22:%221%22,%22count%22:%2220%22,%22start%22:%220%22}&type=query&tk=5dc38484e3f0715c91ae90ea06d19e3d");
                    Map<String,Object> gaodeMap = (Map<String,Object>) JSON.parseObject(gaodeRes,HashMap.class);
                    content = (List<Map>) gaodeMap.get("pois");
                    hashMap.put("url", "http://api.tianditu.gov.cn/");
                    if(CollectionUtils.isEmpty(content)){
                        noSearchList.add(newMap("There is no such government in the current administrative region",cityName));
                        continue;
                    }
                }
                flag : for (int i = 0; i < content.size(); i++) {
                    poi = (Map) content.get(i);
                    Map ext;
                    Map detail_info;
                    try {
                        ext = (Map)poi.get("ext");
                        detail_info = (Map)ext.get("detail_info");
                    }catch (Exception e){
                        if(poi.containsKey("id")){
                            detail_info  = null;
                            poi.put("addr", poi.get("address"));
                        }else {
                            noSearchList.add(newMap("Maybe this POI  in different regions",cityName));
                            System.out.println(new String("Maybe this POI  in different regions".getBytes(),"UTF-8"));
                            poi = null;
                            break;
                        }
                    }

                    if( "".equals(poi.get("name").toString()) && poi.get("name").toString().length() <= 0){
                        name = detail_info.get("name").toString();
                    }else {
                        name = poi.get("name").toString();
                    }

                    if(checkFromConsRule(name,map)) break;

                    if(i == content.size()-1  && !poi.containsKey("id")){
                        String[] key = {"2541786be147d4e463f258eefaaacdcd","2be1ed0cf52ab8ea7d86212bb5bd31b2","97811d9076214e151b33d9ed80cf1f4e","298a568477d3569cb7ccd0977f40f585","2550e50ae16a26b5f754b869500cd8a5"};
                        String gaodeRes = HttpUtil.sendGet(gaodeMapAPI, "postStr={%22keyWord%22:%22"+URLEncoder.encode(cityName + Const.GAODE_DEPARTMENT_NAME, "UTF-8")+"%22,%22level%22:%2220%22,%22mapBound%22:%2288.24219,23.0393,117.55371,46.58907%22,%22queryType%22:%221%22,%22count%22:%2220%22,%22start%22:%220%22}&type=query&tk="+key[(int)(Math.random()*5)]);
                        Map<String,Object> gaodeMap = (Map<String,Object>) JSON.parseObject(new String(gaodeRes.getBytes(),"UTF-8"),HashMap.class);
                        if("0".equals(gaodeMap.get("count").toString())) {
                            noSearchList.add(newMap("There is no such government in the current administrative region",cityName));
                            System.out.println(new String("There is no such government in the current administrative region".getBytes(),"UTF-8"));
                            poi = null;
                            break flag;
                        }
                        List<Map> gaodeList = (List<Map>) gaodeMap.get("pois");
                        for (int j = 0; j < gaodeList.size(); j++) {
                            poi = gaodeList.get(j);
                            name = poi.get("name").toString();
                            if(checkFromConsRule(name,map)){
                                poi.put("addr", poi.get("address"));
                                poi.put("tel", poi.get("phone"));
                                poi.put("area_name", "");
                                hashMap.put("url", "http://api.tianditu.gov.cn/");
                                break flag;
                            }else if(j == gaodeList.size()-1){
                                noSearchList.add(newMap("There is no such government in the current administrative region",cityName));
                                System.out.println(new String("There is no such government in the current administrative region".getBytes("UTF-8")));
                                poi = null;
                                break flag;
                            }
                        }
                    }
                }

                if(poi == null) continue;

                if (poi.containsKey("addr")) {
                    String addr = poi.get("area_name").toString()+poi.get("addr").toString().replace(poi.get("area_name").toString(), "");
                    String[] key = {"5dc38484e3f0715c91ae90ea06d19e3d","bd8d50ae476c5453641f25400ec52843","97811d9076214e151b33d9ed80cf1f4e"};
                    String addrJson = HttpUtil.sendGet("http://api.tianditu.gov.cn/geocoder", "ds={%27keyWord%27:%27" + addr + "%27}&tk="+key[(int)Math.random()*3]);
                    JSONObject jsonObject = JSON.parseObject(new String(addrJson.getBytes(),"UTF-8"));
                    String msg = jsonObject.get("msg").toString();
                    if(msg.equals("ok")){
                        Map tiditu = (Map)jsonObject.get("location");
                        hashMap.put("lng", tiditu.get("lon").toString());
                        hashMap.put("lat", tiditu.get("lat").toString());
                    }else {
                        hashMap.put("lng", "");
                        hashMap.put("lat", "");
                    }
                    hashMap.put("address", addr);

                } else {
                    hashMap.put("address", "");
                }

                if(poi.containsKey("diPointX") && poi.containsKey("diPointY")){
                    hashMap.put("x",poi.get("diPointX").toString());
                    hashMap.put("y",poi.get("diPointY").toString());
                }else {
                    hashMap.put("x","");
                    hashMap.put("y","");
                }

                if(poi.containsKey("admin_info") ){
                    Map<String,String> admin_info = (Map<String,String>)poi.get("admin_info");
                    hashMap.put("area_id", admin_info.get("area_id"));
                }else {
                    hashMap.put("area_id", "");
                }


                hashMap.put("name", name);
                hashMap.put("area_code", area_code);
                if (poi.containsKey("tel") && poi.get("tel").toString().length() > 1) {
                    hashMap.put("phone", poi.get("tel").toString());
                } else {
                    hashMap.put("phone", "");
                }

                System.out.println(hashMap);
                success.add(hashMap);
            } catch (Exception e) {
                noSearchList.add(newMap("Exception poi",cityName));
                System.out.println("未知异常");
                e.printStackTrace();
                continue;
            }
        }
    }

    public static Map<String,String> newMap (String failMsg,String cityName) throws UnsupportedEncodingException {
        String s = new String("cause".getBytes(),"UTF-8");
        HashMap<String, String> noSearchMap = new HashMap<>();
        noSearchMap.put("name", new String((cityName + Const.BAIDU_DEPARTMENT_NAME).getBytes("UTF-8"),"UTF-8"));
        noSearchMap.put("lng", "");
        noSearchMap.put("lat", "");
        noSearchMap.put("phone", "");
        noSearchMap.put("url", "");
        noSearchMap.put("address", "");
        noSearchMap.put(s, new String(failMsg.getBytes("UTF-8")));
        noSearchMap.put("x","");
        noSearchMap.put("y","");
        noSearchMap.put("area_id","");
        noSearchMap.put("area_code","");
        return noSearchMap;
    }

    public static Boolean checkFromConsRule(String name,Map<String, String> map){
        if (Const.REGEX.equals("") && Const.REGEX.length <= 0 ){
            for (int j = 0; j < Const.MORE_DEPARTMENT_NAME.length; j++) {
                if(name.contains(Const.MORE_DEPARTMENT_NAME[j]) && name.contains(map.get("short_name"))){
                    return true;
                }
            }
        }else {
            for (int j = 0; j < Const.REGEX.length; j++) {
                if(Pattern.matches(Const.REGEX[j], name) && name.contains(map.get("short_name"))){
                    return true;
                }
            }
        }
        return false;
    }
}
